// Constants
var OTHER_SHOOT_PROB = 0.8; //the chance of an Other node which is taking action on a given play iteration (Frame) to create a shot rather than an award.
var GAME_FPS = 60;

var GAME_KEYS = 
{
	up_keys : ['w'],
	down_keys : ['x'],
	left_keys : ['a'],
	right_keys : ['d'],
	up_right_keys : ['e'],
	up_left_keys : ['q'],
	down_right_keys : ['c'],
	down_left_keys : ['z']
	
	// new_game : ['n']
	// pause_game : ['p']
}

var KEY_DIRECTION_TO_ANGLE = 
{
	up_keys : 270,
	down_keys : 90,
	left_keys : 180,
	right_keys : 0,
	up_right_keys : 315,
	up_left_keys : 225,
	down_right_keys : 45,
	down_left_keys : 135
}

var OBJECT_SPRITES =
{
	otherShot : 'img/bullet.png',
	award : 'img/coin.png',
	playerShot : 'img/cannonball.png',
	player : 'img/bazooka.png',
	other : 'img/other.png'
}

// Global Methods

function getCounterAngle(angle)
{
    return ((180 + angle) % 360);
}

function translate(x)
{
	return x + gameManager.edgeSize / 2;
}

function drawImage(image, x, y, width, height, angle)
{
	tX = translate(x);
	tY = translate(y);
	gameManager.ctx.save();
	gameManager.ctx.translate(tX, tY);
	gameManager.ctx.rotate(angle * Math.PI / 180);
	gameManager.ctx.drawImage(image, 0, -height / 2, width, height);
	gameManager.ctx.restore();
}

function drawOther(image, x, y, width, height, angle)
{
	tX = translate(x);
	tY = translate(y);
	gameManager.ctx.save();
	gameManager.ctx.translate(tX, tY);
	gameManager.ctx.rotate((angle + 90)* Math.PI / 180);
	gameManager.ctx.drawImage(image, -width / 2, -height / 2, width, height);
	gameManager.ctx.restore();
}

function drawPlayer(image, x, y, width, height, angle)
{
	tX = translate(x);
	tY = translate(y);
	gameManager.ctx.save();
	gameManager.ctx.translate(tX, tY);
	gameManager.ctx.rotate(angle * Math.PI / 180);
	gameManager.ctx.drawImage(image, -width / 2, -height / 2, width, height);
	gameManager.ctx.restore();
}

// utility method to to allow a difference of 'speed'
function isSameLocation(o1, o2)
{
	return (Math.abs(o1.x - o2.x) <= gameManager.movingObjectSpeed) && (Math.abs(o1.y - o2.y) <= gameManager.movingObjectSpeed);
}

// AssetManager
function AssetManager()
{
	this.assets = {};
}

AssetManager.prototype.addImages = function(images) 
{
	$.each(images, function(index, imageUrl)
	{
		var image = new Image();
		image.src = imageUrl;
		assetManager.assets[imageUrl] = image;
	});
}

// PersistentSettings
var gameSettings = 
{
    otherActionProb : 0.002, //the chance of an Other node creating either a shot or an award in a given play iteration (Frame).
    movingObjectSpeed : 1,    //speed of moving objects	
	
	gameInProgress : false
}

// GameManager

function GameManager(ctx)
{
	// 2d canvas context
	this.ctx = ctx;
	
	//board related fields
	this.edgeSize = ctx.canvas.height;

    //difficulty settings
    this.otherActionProb = gameSettings.otherActionProb;
    this.movingObjectSpeed = gameSettings.movingObjectSpeed;

	//score-info related fields
	this.scoreInfo =
	{
		lives: 10,
		score: 0,
		otherShotsHit: 0,
		otherShotsSuffered: 0,
		awardsGathered: 0,
		awardsShotDown: 0,
		maxCombo: 0, //combo - consecutively hitting only OtherShots and without hitting any Awards or getting hit by OtherShots
		currentCombo: 0
	}

	//helper map
	this.otherAngleToSign =
	{
		0 :
		{
			x: 1,
			y: 0
		},


		45 :
		{
			x: 1,
			y: 1
		},

		90 :
		{
			x: 0,
			y: 1
		},

		135 :
		{
			x: -1,
			y: 1
		},

		180 :
		{
			x: -1,
			y: 0
		},

		225 :
		{
			x: -1,
			y: -1
		},

		270 :
		{
			x: 0,
			y: -1
		},

		315 :
		{
			x: 1,
			y: -1
		}
	};
	
}

GameManager.prototype.drawStartGameScreen = function(message)
{
	this.ctx.clearRect(0,0, this.edgeSize, this.edgeSize);
	this.ctx.save();
	this.ctx.font = '20pt Verdana';
	this.ctx.fillStyle = '#ffffff';
	this.ctx.textAlign = 'center';
	this.ctx.fillText(message, translate(0), translate(0));
	this.ctx.restore();
	
	$("#surface").click(function()
	{
		gameManager.init();
		$("#surface").unbind('click');
	});
}

GameManager.prototype.init = function() 
{
	//game-logic related fields
	this.player = new Player();

	this.others = (function ()
	{
		var result = {};

		for (var i = 0; i < 360; i += 45)
		{
			result[i] = new Other(i);
		}

		return result;
	})();

    this.shortcutsBindings = {};
	this.bindGameShortcuts();

	this.interval = setInterval(function () { gameManager.gameLoop(); }, 1000 / GAME_FPS);
	this.isPaused = false;
	gameSettings.gameInProgress = true;
}

GameManager.prototype.draw = function()
{
	
	this.ctx.clearRect(0,0, this.edgeSize, this.edgeSize);

	this.player.draw();
	$.each(this.others, function(angle, other)
	{
		other.draw();
	});	
	
}

GameManager.prototype.play = function()
{
	this.player.play();

	$.each(this.others, function(angle, other)
	{
		other.play();
	});

}

GameManager.prototype.gameLoop = function()
{
	if (this.isGameEnded()) 
	{
		// show current player score, asking for identification if needed
		displayEndGameModal(gameManager.scoreInfo.score);
		
		prepareNewGame();
		gameManager = new GameManager(this.ctx);
		gameManager.drawStartGameScreen("Click me to restart!");
		
	}
	else 
	{
		this.play();
		this.draw();
		this.updateScoreBoard();
	}
}

GameManager.prototype.isGameEnded = function()
{
	return this.scoreInfo.lives <= 0;
}

GameManager.prototype.updateScoreBoard = function()
{
	$("#game-lives .score-value").text(this.scoreInfo.lives);
	$("#game-score .score-value").text(this.scoreInfo.score);
	$("#game-other-shots-hit .score-value").text(this.scoreInfo.otherShotsHit);
	$("#game-other-shots-suffered .score-value").text(this.scoreInfo.otherShotsSuffered);
	$("#game-awards-gathered .score-value").text(this.scoreInfo.awardsGathered);
	$("#game-awards-shot-down .score-value").text(this.scoreInfo.awardsShotDown);
	$("#game-max-combo .score-value").text(this.scoreInfo.maxCombo);
	$("#game-current-combo .score-value").text(this.scoreInfo.currentCombo);
}

GameManager.prototype.updateScore = function(pointsToAdd)
{
	//update the actual score
	this.scoreInfo.score += pointsToAdd;

	//update combos
	if (pointsToAdd > 0) //combo continues on
	{
		this.scoreInfo.currentCombo += pointsToAdd;
	}
	else //combo ended
	{
		if (this.scoreInfo.currentCombo > this.scoreInfo.maxCombo)
		{
			this.scoreInfo.maxCombo = this.scoreInfo.currentCombo;
		}

		this.scoreInfo.lives -= 1;
		this.scoreInfo.currentCombo = 0;
	}
}

GameManager.prototype.bindGameShortcuts = function()
{
	var shortcutLibraryContextParam =
	{
		propagate: false,
		disableInInput: true
	}
	
	$.each(GAME_KEYS, function(keyDirection, keyboardKeys) 
	{
	    if (KEY_DIRECTION_TO_ANGLE[keyDirection] != undefined)
        {
            var callback = function()
            {
                gameManager.player.angle = KEY_DIRECTION_TO_ANGLE[keyDirection];
				gameManager.player.shoot(KEY_DIRECTION_TO_ANGLE[keyDirection]);
            }

            $.each(keyboardKeys, function(index, keyboardKey)
            {
                $.shortcut.add(
                    keyboardKey,
                    callback,
                    shortcutLibraryContextParam
                );

                gameManager.shortcutsBindings[keyboardKey] = callback;
            });
        }
	});
	
}

GameManager.prototype.clearGameShortcuts = function()
{
	if (gameManager.shortcutsBindings)
	{
		$.each(GAME_KEYS, function(keyDirection, keyboardKeys)
		{
			$.each(keyboardKeys, function(index, keyboardKey)
			{
				if (gameManager.shortcutsBindings[keyboardKey])
				{
					$.shortcut.remove(
						keyboardKey,
						gameManager.shortcutsBindings[keyboardKey]);
				}
			});
		});
	}
}

GameManager.prototype.bindManagementShortcuts = function()
{
	var shortcutLibraryContextParam =
	{
		propagate: false,
		disableInInput: true
	}

	var newGameShortcutCallback = function() { $("#new-game").click() };
	var pauseGameShortcutCallback = function() { $("#pause-game").click() };
	
	$.shortcut.add('n', newGameShortcutCallback, shortcutLibraryContextParam);
	$.shortcut.add('p', pauseGameShortcutCallback, shortcutLibraryContextParam);
}

GameManager.prototype.setMovingObjectSpeed = function(speed) 
{
	this.movingObjectSpeed = speed;
	// persist settings to next game
	gameSettings.movingObjectSpeed = speed;
}

GameManager.prototype.setOtherActionProb = function(actionProb)
{
	this.otherActionProb = actionProb;
	// persist settings to next game
	gameSettings.otherActionProb = actionProb;
}

GameManager.prototype.updateOtherMovingObjetWeight = function()
{
    var actionProb = Math.floor((this.otherActionProb * 1000) / 2);
    var speed = Math.floor((this.movingObjectSpeed + 1) / 2);
	
	var weight = actionProb * speed;

	OtherShot.prototype.weight = (-1) * weight;
	Award.prototype.weight = weight;
}

// Entity

function Entity()
{
	this.x = 0;
	this.y = 0;

	this.angle = 0; // [0,360)
}


// Player

function Player()
{
	this.playerShots = [];
}

Player.prototype = new Entity();

Player.prototype.draw = function()
{
	drawPlayer(assetManager.assets[OBJECT_SPRITES.player], this.x, this.y, 70, 70, this.angle);
	$.each(this.playerShots, function(index, playerShot) 
	{
		playerShot.draw();
	});
} 

Player.prototype.play = function()
{
	// we use shallow clone here because as shot might be removed during playerShot.play()
	$.each($.extend({}, this.playerShots), function(index, playerShot)
	{
		playerShot.play();
	});
}

Player.prototype.shoot = function(angle)
{
	this.playerShots.push(new PlayerShot(angle));
}

Player.prototype.removePlayerShot = function(playerShotToRemove)
{
	$.each(this.playerShots, function(index,playerShot)
	{
		if (playerShotToRemove == playerShot)
		{
			gameManager.player.playerShots.splice(index, 1);
			return false;
		}
	});
}

Player.prototype.getFirstShotByAngle = function(angle)
{
	var firstPlayerShotForAngle = undefined;

	$.each(this.playerShots, function(index, playerShot)
	{
		if (playerShot.angle == angle)
		{
			firstPlayerShotForAngle = playerShot;
			return false;
		}
	});

	return firstPlayerShotForAngle;
}


// Other

function Other(angle)
{
	this.angle = angle;
	this.otherMovingObjects = [];

	this.x = Math.floor(gameManager.otherAngleToSign[angle].x * gameManager.edgeSize / 2);
	this.y = Math.floor(gameManager.otherAngleToSign[angle].y * gameManager.edgeSize / 2);
}

Other.prototype = new Entity();

Other.prototype.draw = function()
{
    drawOther(assetManager.assets[OBJECT_SPRITES.other], this.x, this.y, 70, 70, this.angle);

	$.each(this.otherMovingObjects, function(index, otherMovingObject)
	{
		otherMovingObject.draw();
	});
}

Other.prototype.play = function()
{
	// we don't use isSameLocation because other is static 
	if (this.otherMovingObjects.length == 0 ||
		this.otherMovingObjects[this.otherMovingObjects.length-1].x != this.x ||
		this.otherMovingObjects[this.otherMovingObjects.length-1].y != this.y)
	{
		//we only wish to possibly create an OtherMovingObject if one hasn't been created yet in this iteration -
		//this could have already happened if a PlayerShot has hit the counter-Other of this Other, and re-emerged
		//as an OtherShot from this Other.

		if (Math.random() <= gameManager.otherActionProb)
		{
			if (Math.random() <= OTHER_SHOOT_PROB)
				this.shoot();
			else
				this.award();
		}
	}

	// we use shallow clone here because as shot might be removed during otherMovingObject.play()
	$.each($.extend({}, this.otherMovingObjects), function(index, otherMovingObject)
	{
		otherMovingObject.play();
	});
}

Other.prototype.shoot = function()
{
	this.otherMovingObjects.push(new OtherShot(this.angle, this.x, this.y));
}

Other.prototype.award = function()
{
	this.otherMovingObjects.push(new Award(this.angle, this.x, this.y));
}


// MovingObject

function MovingObject()
{

}

MovingObject.prototype = new Entity();

// OtherMovingObject

function OtherMovingObject(weight)
{
	this.weight = weight;
	this.type = 'OtherMovingObject';
}

OtherMovingObject.prototype = new MovingObject();

OtherMovingObject.prototype.draw = function() 
{

}

OtherMovingObject.prototype.play = function()
{
	this.x -= gameManager.otherAngleToSign[this.angle].x * gameManager.movingObjectSpeed;
	this.y -= gameManager.otherAngleToSign[this.angle].y * gameManager.movingObjectSpeed;

	//check if we hit any other object
	var playerShot = gameManager.player.getFirstShotByAngle(getCounterAngle(this.angle));
	if (playerShot && isSameLocation(playerShot, this)) //checking if we've hit the furthest shot of the player in this direction
	{
		this.hitPlayerShot(playerShot);
	}
	else if (isSameLocation(this, { x : 0, y : 0})) 
	{
		this.hitPlayer();
	}
}

OtherMovingObject.prototype.hitPlayerShot = function(playerShot)
{
	playerShot.hitOtherMovingObject(this);
}

OtherMovingObject.prototype.hitPlayer = function()
{
	//update score - here we add the weight of the current OtherMovingObject to the score,
	//so letting an OtherShot hit you is bad, letting an Award hit you is good.
	gameManager.updateScore(this.weight);

	if (this.type == 'OtherShot')
	{
	    gameManager.scoreInfo.otherShotsSuffered++;
    }
    else
    {
        gameManager.scoreInfo.awardsGathered++;
    }

	//remove this OtherMovingObject object from the game
	gameManager.others[this.angle].otherMovingObjects.splice(0, 1); //removing the first OtherMovingObject of this Other
}


// OtherShot

function OtherShot(angle, x, y)
{
	this.x = x;
	this.y = y;
	this.angle = angle;
	this.type = 'OtherShot';
}

OtherShot.prototype = new OtherMovingObject(-1); // -1 default damage, changed by difficulty settings

OtherShot.prototype.draw = function()
{
	drawImage(assetManager.assets[OBJECT_SPRITES.otherShot], this.x, this.y, 20, 20, this.angle);
}

// Award

function Award(angle, x, y)
{
	this.x = x;
	this.y = y;
	this.angle = angle;
	this.type = 'Award';
}

Award.prototype = new OtherMovingObject(1); // 1 default award, changed by difficulty settings

Award.prototype.draw = function()
{
	drawImage(assetManager.assets[OBJECT_SPRITES.award], this.x, this.y, 20, 20, this.angle);
}

// PlayerShot

function PlayerShot(angle)
{
	this.angle = angle;
}

PlayerShot.prototype = new MovingObject();

PlayerShot.prototype.draw = function()
{
	drawImage(assetManager.assets[OBJECT_SPRITES.playerShot], this.x, this.y, 20, 20, this.angle);
}

PlayerShot.prototype.play = function()
{
	this.x += gameManager.otherAngleToSign[this.angle].x * gameManager.movingObjectSpeed;
	this.y += gameManager.otherAngleToSign[this.angle].y * gameManager.movingObjectSpeed;

	//check if we hit any other object
	var counterOther = gameManager.others[this.angle];
	var counterObjects = counterOther.otherMovingObjects;
	if (counterObjects.length > 0)
	{
		//there are OtherMovingObjects coming in our direction. check if we've any
		var firstCounterObject = counterObjects[0]; //only need to check the first counter object (since it's the closest to the Player)
		if (isSameLocation(firstCounterObject, this)) // We HAVE to check x and y
		{
			this.hitOtherMovingObject(firstCounterObject);
		}
	}
	// we don't use isSameLocation because other is static 
	else if (isSameLocation(counterOther, this)) 
	{
		this.hitOther(counterOther);
	}
}

PlayerShot.prototype.hitOtherMovingObject = function(otherMovingObject)
{
	//update score - we give the opposite to the weight,
	//meaning shooting down an OtherShot is good, shooting down an Award is bad.
	gameManager.updateScore((-1)*otherMovingObject.weight);

	//update hits
	if (otherMovingObject.type == 'OtherShot')
	{
		gameManager.scoreInfo.otherShotsHit++;
	}
	else //otherMovingObject.type == 'Award')
	{
		gameManager.scoreInfo.awardsShotDown++;
	}

	//remove the clashing playerShot and otherMovingObject from the game
	gameManager.player.removePlayerShot(this);
	gameManager.others[this.angle].otherMovingObjects.splice(0, 1);
}

PlayerShot.prototype.hitOther = function(other)
{
	//remove this PlayerShot from the game
	gameManager.player.removePlayerShot(this);

	//shoot from the counter-Other to the hit Other
	gameManager.others[getCounterAngle(this.angle)].shoot();

}

function prepareNewGame()
{
	if (gameManager)
	{
		clearInterval(gameManager.interval);
		gameManager.clearGameShortcuts();
	}
		
	$("#pause-game").text("Pause Game (P)");
}

$(function()
{
	var ctx = $("#surface")[0].getContext("2d");
	
	// Global Variables
	assetManager = new AssetManager();
	assetManager.addImages(
	[
		OBJECT_SPRITES.otherShot, 
		OBJECT_SPRITES.award, 
		OBJECT_SPRITES.playerShot,
		OBJECT_SPRITES.player,
		OBJECT_SPRITES.other,
	]);


	gameManager = new GameManager(ctx);
	
	gameManager.bindManagementShortcuts();
	gameManager.drawStartGameScreen("Click me to start!");

    //registering to click events

	$("#pause-game").click(function()
    {
		if (gameSettings.gameInProgress)
		{
			if (gameManager.isPaused)
			{
				gameManager.bindGameShortcuts();
				gameManager.interval = setInterval(function () { gameManager.gameLoop(); }, 1000 / GAME_FPS);
				$(this).text("Pause Game (P)");
			}
			else
			{
				gameManager.clearGameShortcuts();
				clearInterval(gameManager.interval);
				$(this).text("Unpause Game (P)");
			}

			gameManager.isPaused = !gameManager.isPaused;
		}
    });

    $("#new-game").click(function()
    {
        prepareNewGame();
        gameManager = new GameManager(ctx);
        gameManager.init();
    });

    $(".speed-setting-option-text").click(function()
    {
        gameManager.setMovingObjectSpeed(parseInt(this.title));
		gameManager.updateOtherMovingObjetWeight();
        $(".speed-setting-option-text").removeClass("selected-game-setting");
        $(this).addClass("selected-game-setting");
    });

    $(".action-setting-option-text").click(function()
    {
        gameManager.setOtherActionProb(parseInt(this.title) / 1000);
		gameManager.updateOtherMovingObjetWeight();
        $(".action-setting-option-text").removeClass("selected-game-setting");
        $(this).addClass("selected-game-setting");
    });

    $("#game-rules-title").click(function()
    {
        $("#game-rules-text").toggle(250);
    });

    $("#speed-setting").click(function()
    {
        $(".speed-setting-option-list").toggle(250);
    });

    $("#action-setting").click(function()
    {
        $(".action-setting-option-list").toggle(250);
    });
});

/////////////////////////////////////////////////////////////////

//forgive me, i'm sick and lazy.
var isLoggingInAfterGameEnded = false;
var afterGameCurrentScore = 0;
var oauthPrefix = 'https://facebook.com/dialog/oauth?client_id=169613613143468&redirect_uri=';
var oauthSuffix = '%3A%2F%2Fsurroundedgame.appspot.com%2Ffblogin&scope=publish_stream,publish_actions,offline_access';
var oauthUrl = '';

var USER_IDENTIFICATION_STATE_GUEST = "guest-user";
var USER_IDENTIFICATION_STATE_REGISTERED = "registered-user";
var user = 
{
	identificationState : USER_IDENTIFICATION_STATE_GUEST,
	userName : null,
	userHighScore : 0,	
}

$(document).ready(function()
{
	
	var loc = new String(document.location.toString()); 
	if (loc.indexOf("https://") != -1)
	{	
		oauthUrl = oauthPrefix + 'https' + oauthSuffix;
	}
	else
	{
		oauthUrl = oauthPrefix + 'http' + oauthSuffix;
	}
	
	$(".fb_button_text a").attr('href', oauthUrl);
	
	bindEvents();
	
	if (user.isUsernameOvertaken)
	{
		handleUsernameOvertaken(false);
	}
	else
	{
		refreshUserState();
	}	

});


function bindEvents()
{	
	var modalWaitWithCallbackWithScoreArgument = function(callback)
	{
		var currentScore = parseInt($('#game-end-box .game-score').text());
		
		$.modal.close();
		
		// hack needed so modal plugin finishes what it has to do
		// couldn't find a proper callback hook
		setTimeout(function() { callback(currentScore); }, 10);	
	}
	
	$("#game-end-box #showIdentificationModalButton").click(function()		
	{	isLoggingInAfterGameEnded = true;
		afterGameCurrentScore = parseInt($('#game-end-box .game-score').text());
		//go auth @ FB
		window.open(oauthUrl, 'Login with Facebook');
	});	
	
	$("#game-end-box #skipIdenticicationModalButton").click(function()
	{
		modalWaitWithCallbackWithScoreArgument(handleScoreAndShowHighScores);
	});
	
	$("#game-end-box #continueToHighscoresButton").click(function()
	{
		modalWaitWithCallbackWithScoreArgument(handleScoreAndShowHighScores);
	});
}

		
function refreshUserState()
{		
	$("#user-name").text(user.userName);
		
	if (user.identificationState != USER_IDENTIFICATION_STATE_GUEST)
	{	
		$("#game-user-details-score").show();
		$("#user-high-score").text(user.userHighScore);
		$("#log-in").hide();
		$("#log-out").show();
	}
	else
	{
		$("#game-user-details-score").hide();
		$("#log-in").show();
		$("#log-out").hide();
	}	
}


function displayEndGameModal(score)
{		

	$('#game-end-box .game-score').text(score);

	$('#game-end-state-guest').hide();
	$('#game-end-state-non-guest').hide();
	
	var modalHeight;
	if (user.identificationState == USER_IDENTIFICATION_STATE_GUEST && score > 0)
	{	
		$('#game-end-state-guest').show();
		modalHeight = 185;
	}
	else
	{
		$('#game-end-state-non-guest').show();
		modalHeight = 150;
	}
		
	$("#game-end-box").modal(
	{
		containerCss: 
		{
			width: 400,
			height: modalHeight
		},
		onOpen: function(dialog)
		{
			dialog.overlay.fadeIn('slow');
			dialog.data.fadeIn('slow');
			dialog.container.fadeIn('slow');
		}
	});
}

function handleScoreAndShowHighScores(score)
{
	if (user.identificationState != USER_IDENTIFICATION_STATE_GUEST)
	{
		// send player's score to server
		// and only then fetch highscores
		sendScore(score, getHighScores);
	}
	else 
	{
		// show high scores
		getHighScores();	
	}

}


function getHighScores()
{	
	$.getJSON("ajax", { command : "highScores" }, function(data)
	{
		displayHighScoresModal(data.highScores);
	});
}

function sendScore(currentScore, callbackMethod)
{
	ajaxCallParams = 
	{
		command: "addScore",
		score: currentScore
	}
	
	$.post("ajax", ajaxCallParams, function(rawData)
	{
		var data = $.parseJSON(rawData);

		if (data.isUsernameOvertaken)
		{
			handleUsernameOvertaken(true);
		}
		else
		{		
			if (data.isScoreAdded)
			{
				user.userHighScore = data.currentBestScore;
				$("#game-user-details-score .game-user-details-value").text(user.userHighScore);	
			}		
			
			if (callbackMethod != undefined)
			{
				callbackMethod();
			}
		}
	});	 
}

function displayHighScoresModal(rawHighScores)
{	
	var tableData = "<table width=340><tr><th></th><th>Name</th><th>Score</th></tr>";
	$.each(rawHighScores, function(index, scoreData)
	{
		tableData += "<tr><td>" + '<img src="' + scoreData["userPicURL"] + '" width=35 height=35 style="vertical-align: middle;" />';
		
		tableData += "</td><td>"+ scoreData["userName"] +"</td><td>"+ scoreData["userScore"] +"</td></tr>";
	});
	tableData += "</table>";
	
	$("#high-scores-box #table-data").html(tableData);
	
	$("#high-scores-box").modal(
	{
		containerCss: 
		{
			width: 350,
			height: 450
		},
		onOpen: function(dialog)
		{
			dialog.overlay.fadeIn('slow');
			dialog.data.fadeIn('slow');
			dialog.container.fadeIn('slow');
		},
		onClose: function(dialog)
		{
			dialog.overlay.fadeOut('slow');
			dialog.data.fadeOut('slow');
			dialog.container.fadeOut('slow', $.modal.close);
		}
	});
}

function hideModalErrorAlert() 
{
	$("#error-notification").hide();
}

function showModalErrorAlert(message) 
{
	$("#error-notification").text(message).show();
}

function loginSucceeded(userName, userScore) 
{
	user.identificationState = USER_IDENTIFICATION_STATE_REGISTERED;
	user.userName = userName;
	user.userHighScore = userScore;
	
	refreshUserState();
	
	if (isLoggingInAfterGameEnded)
	{
		handleScoreAndShowHighScores(afterGameCurrentScore);
		isLoggingInAfterGameEnded = false;
		afterGameCurrentScore = 0;
		$.modal.close();
	}	
}